//
// Created by 文道江 on 15/11/25.
// Copyright (c) 2015 WenDaojiang. All rights reserved.
//

#import "KVStorage.h"
#import "FZEasyFile.h"

@implementation KVStorageModel

+ (NSDictionary *)propertiesTypes {
    return @{@"key" : NSStringFromClass([NSString class]),
            @"value" : NSStringFromClass([NSData class])};
}

+ (NSString *)tableName {
    return @"KVStorage";
}

@end

@implementation KVStorage

+ (KVStorage *)sharedStorage {
    static KVStorage *_instance = nil;

    @synchronized (self) {
        if (_instance == nil) {
            _instance = [[self alloc] init];
        }
    }

    return _instance;
}

+ (void)setKey:(NSString *)key Value:(id)value {
    [[self sharedStorage] setKey:key Value:value];
}

+ (id)getValue:(NSString *)key {
    return [[self sharedStorage] getValue:key];
}

+ (NSDictionary *)getJsonValue:(NSString *)key {
    NSData *data = [[self sharedStorage] getValue:key];
    if(data != nil){
        NSError *err;
        NSDictionary *jsonData = [NSJSONSerialization JSONObjectWithData:data options:NSJSONReadingMutableLeaves error: &err];
        if(err == nil){
            return jsonData;
        }
    }
    return nil;
}

- (instancetype)init {
    self = [super init];
    if (self) {
        _dbPath = [FZEasyFile fullFileName:@"KVStorage.db"];
        NSLog(@"_%@", _dbPath);
        _manager = [DTSManager sharedManager];
        [_manager addManagedClass:[KVStorageModel class]];
        [_manager openDataBaseAtPath:_dbPath
                          withSchema:^(FMDatabase *db, int *schemaVersion) {
                              [db beginTransaction];
                              void (^failedAt)(int statement) = ^(int statement) {
                                  int lastErrorCode = db.lastErrorCode;
                                  NSString *lastErrorMessage = db.lastErrorMessage;
                                  [db rollback];
                                  NSAssert3(0, @"Migration statement %d failed, code %d: %@", statement, lastErrorCode, lastErrorMessage);
                              };
                              if (*schemaVersion < 1) {
                                  if (![db executeUpdate:
                                          @"CREATE TABLE KVStorage ("
                                                  @" objectId INTEGER UNIQUE NOT NULL PRIMARY KEY AUTOINCREMENT,"
                                                  @" key   TEXT NOT NULL DEFAULT '',"
                                                  @" value   BLOB"
                                                  @");"
                                  ])
                                      failedAt(1);

                                  *schemaVersion = 1;
                              }
                              [db commit];
                          }];
    }

    return self;
}

- (void)setKey:(NSString *)key Value:(id)value {
    KVStorageModel *kvStorageModel = [self getKVStorageForKey:key];
    if (kvStorageModel == nil) {
        kvStorageModel = [[KVStorageModel alloc] init];
        kvStorageModel.key = key;
    }
    if ([value isKindOfClass: NSDictionary.class]){
        NSError *err;
        value = [NSJSONSerialization dataWithJSONObject:value options:NSJSONWritingPrettyPrinted error: &err];
        if(err != nil){
            value = [@"" dataUsingEncoding:NSUTF8StringEncoding];
        }
    }
    kvStorageModel.value = value;
    [kvStorageModel save];
}

- (id)getValue:(NSString *)key {
    KVStorageModel *kvStorageModel = [self getKVStorageForKey:key];
    if (kvStorageModel) {
        return kvStorageModel.value;
    }
    return nil;
}

- (KVStorageModel *)getKVStorageForKey:(NSString *)key {
    NSNumber *valueId = [self getIdForKey:key];
    if (!valueId) {
        return nil;
    }
    KVStorageModel *kvStorageModel = (id) [_manager objectWithId:valueId objectClass:[KVStorageModel class]];
    if (kvStorageModel) {
        return kvStorageModel;
    }
    //NSLog(@"result %@", kvStorageModel.value);
    return nil;
}

- (NSNumber *)getIdForKey:(NSString *)key {
    NSArray *result = [_manager arrayWithIdsFromClass:[KVStorageModel class] whereProperty:@"key" hasValue:key orderDesc:YES];
    return result && result.count > 0 ? result[0] : nil;
}

@end
